package Kaolabo;

use strict;
use warnings;

use LWP::UserAgent;
use HTTP::Request;
use Imager;
use File::Spec;

use base qw(Class::Accessor);

__PACKAGE__->mk_accessors(qw( target_file convert_file uri apikey imager response_xml face_data area face_area unface_area));

sub access{
    my $self = shift;

    my $target_file = $self->target_file;
    my $uri = $self->uri.$self->apikey;
    my $request_content;

    my $imager = Imager->new;
    $imager->read( file => $target_file ) or die $imager->errstr;
    $imager->write(type=>'jpeg', data=>\$request_content);
    
    my $request = HTTP::Request->new( 'POST' => $uri);
    $request->header('Content-Type' => 'image/jpeg');
    
    $request->content($request_content)
      if( $request_content );
    
    my $ua = LWP::UserAgent->new;

    my $response = $ua->request($request);
    unless ( $response->is_success ) {
        warn $response->status_line."\n";
    }

    $self->response_xml($response->content);
    $self->_parser();
    $self->imager($imager);

    $self->_area_score();
    return $response;
}

sub _parser{
    my $self = shift;

    my $content = $self->response_xml();
    my $face_data = [];
    while( $content =~ s/<face(.+?)<\/face// ){
        my $node = $1;
        my ($height,$score,$width,$face_x,$face_y,$left_eye_x,$left_eye_y,$right_eye_x,$right_eye_y)
          = (0,0,0,0,0,0,0,0,0);

        ($height,$score,$width,$face_x,$face_y) = ($1,$2,$3,$4,$5)
          if( $node =~ /height="(\d+)" score="(\d+)" width="(\d+)" x="(\d+)" y="(\d+)"/ );

        ($left_eye_x,$left_eye_y) = ($1,$2)
          if( $node =~ /left\-eye x="(\d+)" y="(\d+)"/i );

        ($right_eye_x,$right_eye_y) = ($1,$2)
          if( $node =~ /right\-eye x="(\d+)" y="(\d+)"/i );

        my $center_x = $width / 2 + $face_x;
        my $center_y = $height / 2 + $face_y;
        push @{$face_data},{
                               height => $height,
                               score => $score,
                               width => $width,
                               face_x => $face_x,
                               face_y => $face_y,
                               left_eye_x => $left_eye_x,
                               left_eye_y => $left_eye_y,
                               right_eye_x => $right_eye_x,
                               right_eye_y => $right_eye_y,
                               left_eye_x => $left_eye_x,
                               left_eye_y => $left_eye_y,
                               right_eye_x => $right_eye_x,
                               right_eye_y => $right_eye_y,
                               center_x => $center_x,
                               center_y => $center_y,
                          };
    }

    $self->face_data($face_data);

    return; 
}

use Data::Dumper;
sub _area_score{
    my $self = shift;

    my $w = $self->imager->getwidth();
    my $h = $self->imager->getheight();
    my $ddx = $w / 3;
    my $ddy = $h / 3;

    my @area;
    my $area_number = 0;
    for my $i (1..3){
        $area_number++;
        push @area,{area_number=>$area_number, min_x=>$ddx * ($i - 1), min_y=>0, max_x=>$ddx * $i, max_y=>$ddy, point=>0};
    }
    for my $i (1..3){
        $area_number++;
        push @area,{area_number=>$area_number, min_x=>$ddx * ($i - 1), min_y=>$ddy, max_x=>$ddx * $i, max_y=>$ddy * 2, point=>0};
    }
    for my $i (1..3){
        $area_number++;
        push @area,{area_number=>$area_number, min_x=>$ddx * ($i - 1), min_y=>$ddy * 2, max_x=>$ddx * $i, max_y=>$ddy * 3, point=>0};
    }

    my $face_data = $self->face_data();

    for my $f (@{$face_data}){
        for my $a (@area){
            if( $a->{max_x} > $f->{center_x} && $a->{max_y} > $f->{center_y} ){
                $a->{point}++;
                last;
            }
        }
    }
    $self->area(\@area);
#    my @sort_area = sort {$a->{point}<=>$b->{point}} @area;
    my @unface_area = grep({$_->{point}==0} @area);
    $self->unface_area(\@unface_area);
    my @face_area = grep({$_->{point}!=0} @area);
    $self->face_area(\@face_area);

    return;
}

sub effect_face{
    my $self = shift;
    my $args = shift;
    my $effect = $args->{type} || 'line';
    my $color = $args->{color} || '#000000';
    my $imager = $self->imager;
    
    my $face_data = $self->face_data;
    for my $f ( @{$self->face_data} ){
        $imager->box(
            xmin => $f->{face_x}, ymin => $f->{face_y},
            xmax => $f->{face_x} + $f->{width}, ymax => $f->{face_y} + $f->{height},
            color => $color,
            filled => 1,
        ) if( $effect eq "box");
    
        my $border_h = $f->{height} * 0.12;
        $imager->box(
           # xmin => $f->{face_x}, ymin => $f->{right_eye_y} - $border_h,
            xmin => $f->{face_x}, ymin => $f->{left_eye_y} - $border_h,
            xmax => $f->{face_x} + $f->{width}, ymax => $f->{left_eye_y} + $border_h,
            color => $color,
            filled => 1,
        ) if( $effect eq "line");
    }
    return; 
}

sub write{
    my $self = shift;
    my $convert_file = shift;
    $convert_file ||= $self->convert_file;
    my $imager = $self->imager;
    $imager->write( file => $convert_file, jpegquality => 100 ) or die $imager->errstr;
    return;
}
1;

